package com.fadadianqi.mall.service;


import com.fadadianqi.mall.dao.NavDAO;
import com.fadadianqi.mall.model.Nav;
import com.fadadianqi.mall.product.dao.NavItemSPUDAO;
import com.fadadianqi.mall.product.model.NavItemSPU;
import com.yeqiangwei.commons.util.ValidatorHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;


@Service
public class NavService {

    @Autowired
    private NavDAO navDAO;
    @Autowired
    private NavItemSPUDAO navItemSPUDAO;

    public List<Nav> findAll() {
        return navDAO.findAll();
    }

    public Nav findById(String id) {
        return navDAO.getById(id);
    }

    /**
     * 更新排序
     * 给当前导航的同层次的下级导航的排序字段加1
     *
     * @param currentNav
     */
    public void updateOrderForLayer(Nav currentNav) {
        navDAO.updateOrderForLayer(currentNav);
    }

    public void update(Nav nav) {
        navDAO.update(nav);
    }

    /**
     * @param nav
     */
    public void save(Nav nav) {
        navDAO.create(nav);
    }

    private void decLayer(Nav nav) {
        List<Nav> childrenNavs = navDAO.findChildrenByParent(nav);
        if (ValidatorHelper.isEmpty(childrenNavs)) {
            return;
        }
        for (Nav children : childrenNavs) {
            children.setLayer(children.getLayer() - 1);
            navDAO.update(children);
            decLayer(children);
        }

    }

    private void incLayer(Nav nav) {
        List<Nav> childrenNavs = navDAO.findChildrenByParent(nav);
        if (ValidatorHelper.isEmpty(childrenNavs)) {
            return;
        }
        for (Nav children : childrenNavs) {
            children.setLayer(children.getLayer() + 1);
            navDAO.update(children);
            incLayer(children);
        }
    }

    public void moveUp(Nav nav) throws Exception {
        //第一种情况，最简单的，这个菜单下面也没有子菜单了，并且离父级菜单也很远
        //这时候只需要跟他的上一层次菜单对调就可以了。
        //首先查出上一级菜单
        if (nav.getOrderby() > 0) {
            //orderby的值对调
            int currNav = nav.getOrderby();
            Nav upperNav = navDAO.findUpperNav(nav.getParentId(), nav.getOrderby() - 1);
            nav.setOrderby(upperNav.getOrderby());
            upperNav.setOrderby(currNav);
            navDAO.update(nav);
            navDAO.update(upperNav);

        } else if (nav.getLayer() - 1 >= 0) { //如果<0的话就证明已经是顶层菜单，就不能在往上移动了
            //如果上一级已经没有菜单了，即当前菜单是当前Layer的顶级菜单，则layer层-1，并且此菜单的子菜单layer层也-1
            Nav fatherNav = navDAO.getById(nav.getParentId());
            nav.setLayer(nav.getLayer() - 1);
            navDAO.update(nav);
            //其余所有子菜单layer层都-1
            decLayer(nav);
            /**
             * 移动过得菜单，剩余的项目也需要对order进行重新排序，因为相当于有一个菜单升级了，layer-1，则原本余下的菜单order应该从0开始重新排序
             */
            flushNavOrder(fatherNav.getLayer() + 1);
            flushNavOrder(nav.getLayer());
        }

    }

    /**
     * 逻辑和moveUp类似
     *
     * @param nav
     * @throws Exception
     */
    public void moveDown(Nav nav) throws Exception {
        Nav lowerNav = navDAO.findLowerNav(nav.getParentId(), nav.getOrderby() + 1);
        if (lowerNav != null) {
            int currOrderby = nav.getOrderby();
            nav.setOrderby(lowerNav.getOrderby());
            lowerNav.setOrderby(currOrderby);
            navDAO.update(lowerNav);
            navDAO.update(nav);
        } else {
            nav.setLayer(nav.getLayer() + 1);
            navDAO.update(nav);
            incLayer(nav);
            flushNavOrder(nav.getLayer());
            flushNavOrder(nav.getLayer() + 1);
        }

    }

    private void flushNavOrder(int layer) {
        int index = 0;
        List<Nav> otherNavChildrenNavs = navDAO.findNavByLayer(layer);
        for (Nav restNav : otherNavChildrenNavs) {
            restNav.setOrderby(index);
            navDAO.update(restNav);
            index++;
        }
    }

    public Nav getById(String id) {
        if (ValidatorHelper.isEmpty(id)) {
            return null;
        }
        return navDAO.getById(id);
    }

    public List<Nav> findRootItems() {
        return navDAO.findRootItems();
    }

    /**
     * 只查询父节点的最近一层子节点
     *
     * @param parent
     * @return
     */
    public List<Nav> findChildrenByParent(Nav parent) {
        return navDAO.findChildrenByParent(parent);
    }

    /**
     * created by aroot
     * <p/>
     * 按树形显示结构排序查找根节点下的所有子节点
     * 显示主干支，包含当前传入对象
     * 从当前对象向下查找
     *
     * @param rootId
     * @return
     */
    public List<Nav> showTreeBranchs(String rootId) {
        NavTreeBuilder ntb = new NavTreeBuilder();
        ntb.buildBranchs(rootId);
        return ntb.getTreeList();
    }

    /**
     * 显示枝干不包含当前对象
     * 从当前对象向下查找
     *
     * @param currentId
     * @return
     */
    public List<Nav> showTreeTwig(String currentId) {
        return showTreeTwig(getById(currentId));
    }

    /**
     * 显示枝干不包含当前对象
     * 从当前对象向下查找
     *
     * @param current
     * @return
     */
    public List<Nav> showTreeTwig(Nav current) {
        if (current == null) {
            return null;
        }
        NavTreeBuilder ntb = new NavTreeBuilder();
        ntb.buildTwig(current);
        return ntb.getTreeList();
    }

    /**
     * created by aroot
     * 查询全部并封装成树形结构顺序展示在页面上
     *
     * @return
     */
    public List<Nav> showTreeList() {
        NavTreeBuilder ntb = new NavTreeBuilder();
        ntb.build();
        return ntb.getTreeList(); // 临时的
    }

    public List<Nav> showTreeListWithoutIsHidden() {
        // TODO 查询全部没有被隐藏掉的菜单，用于展示在页面上。
        NavTreeBuilder ntb = new NavTreeBuilder();
        ntb.build();
        return ntb.getTreeList(); // 临时的
    }

    public List<Nav> findBySpuId(String spuId) {
        List<NavItemSPU> _list = navItemSPUDAO.findBySpuId(spuId);
        List<Nav> list = new ArrayList<Nav>();
        if(ValidatorHelper.isNotEmpty(_list)) {
            for(NavItemSPU n : _list) {
                Nav nav = getById(n.getNavId());
                list.add(nav);
            }
        }
        return list;
    }

    public static class NavSaveResultPojo {

        private boolean saveResult;
        private String errMsg;

        public boolean isSaveResult() {
            return saveResult;
        }

        public void setSaveResult(boolean saveResult) {
            this.saveResult = saveResult;
        }

        public String getErrMsg() {
            return errMsg;
        }

        public void setErrMsg(String errMsg) {
            this.errMsg = errMsg;
        }
    }

    public class NavTreeBuilder {

        private List<Nav> treeList;

        private LinkedList bufList;

        public NavTreeBuilder() {
            treeList = new ArrayList<Nav>();
            bufList = new LinkedList();
        }

        private void _build(Nav nav) {
            List<Nav> children = findChildrenByParent(nav);
            if (ValidatorHelper.isNotEmpty(children)) {
                for (Nav c : children) {
                    treeList.add(c);
                    _build(c);
                }
            }
        }

        public void build() {
            List<Nav> rootList = findRootItems();
            for (Nav root : rootList) {
                treeList.add(root);
                _build(root);
            }
        }

        public void buildBranchs(String rootId) {
            Nav root = getById(rootId);
            treeList.add(root);
            _build(root);
        }

        public void buildTwig(String currentId) {
            buildTwig(getById(currentId));
        }

        /**
         * 根据当前ID向上查找父类
         *
         * @param current
         */
        private void _buildTwig(Nav current) {
            Nav nav = getById(current.getParentId());
            if (null != nav) {
                bufList.addFirst(nav);
                _buildTwig(nav);
            }
        }

        /**
         * 根据当前ID向上查找父类
         *
         * @param current
         */
        public void buildTwig(Nav current) {
            bufList.add(current);
            _buildTwig(current);
            treeList.addAll(bufList);
        }


        public List<Nav> getTreeList() {
            return treeList;
        }
    }
}
